<template>
    <el-drawer v-model="visible" title="日志详情" :size="600" direction="rtl" :before-close="handleClose" destroy-on-close
        class="log-detail-drawer">
        <div class="log-detail" v-if="log && log.id">
            <el-descriptions :column="1" border size="">
                <el-descriptions-item label="日志ID">
                    {{ log.id }}
                </el-descriptions-item>
                <el-descriptions-item label="任务名称">
                    {{ log.timerTask?.name || log.task_name || '-' }}
                </el-descriptions-item>
                <el-descriptions-item label="日志级别">
                    <el-tag :type="log.status == 1 ? 'success' : 'danger'" size="">
                        {{ log.status == 1 ? '成功' : '失败' }}
                    </el-tag>
                </el-descriptions-item>
                <el-descriptions-item label="执行时间">
                    {{ formatTime(log.add_time) }}
                </el-descriptions-item>
                <el-descriptions-item label="执行耗时">
                    {{ log.exec_time }}ms
                </el-descriptions-item>
                <el-descriptions-item label="内存消耗">
                    {{ formatMemory(log.exec_memory) }}
                </el-descriptions-item>
            </el-descriptions>

            <div class="log-message-detail">
                <h4>详细信息</h4>
                <div class="message-content" v-if="parsedMessages.length > 0">
                    <div v-for="(msgItem, index) in parsedMessages" :key="index" class="message-item"
                        :class="`message-level-${msgItem.level}`">
                        <div class="message-header">
                            <el-tag :type="getTagType(msgItem.level)" size="small" class="level-tag">
                                {{ msgItem.level.toUpperCase() }}
                            </el-tag>
                            <span class="message-time">{{ formatTime(msgItem.time) }}</span>
                        </div>
                        <div class="message-body">
                            <div v-if="isStackTrace(msgItem.msg)" class="stack-trace">
                                <div class="simple-message">{{ getErrorSummary(msgItem.msg) }}</div>
                                <el-collapse v-if="getStackTrace(msgItem.msg)" accordion size="small">
                                    <el-collapse-item title="查看调用堆栈" name="stack">
                                        <pre class="stack-content">{{ getStackTrace(msgItem.msg) }}</pre>
                                    </el-collapse-item>
                                </el-collapse>
                            </div>
                            <div v-else class="simple-message">
                                {{ msgItem.msg }}
                            </div>
                        </div>
                    </div>
                </div>
                <div v-else-if="typeof log.message === 'string'" class="message-content">
                    <div class="simple-message">{{ log.message }}</div>
                </div>
                <div v-else class="message-content">
                    <div class="simple-message">-</div>
                </div>
            </div>
        </div>
    </el-drawer>
</template>

<script>
import { ElCollapse, ElCollapseItem } from 'element-plus'

export default {
    name: 'LogDetail',
    components: {
        ElCollapse,
        ElCollapseItem
    },
    props: {
        modelValue: {
            type: Boolean,
            default: false
        },
        log: {
            type: Object,
            default: () => ({})
        }
    },
    emits: ['update:modelValue', 'close'],
    computed: {
        visible: {
            get() {
                return this.modelValue
            },
            set(value) {
                this.$emit('update:modelValue', value)
            }
        },

        // 解析消息数组
        parsedMessages() {
            if (!this.log || !this.log.message) {
                return []
            }

            try {
                // 如果message是字符串，尝试解析为JSON
                let message = this.log.message
                if (typeof message === 'string') {
                    try {
                        message = JSON.parse(message)
                    } catch (e) {
                        // 如果解析失败，当作普通字符串处理
                        return [{
                            level: 'info',
                            msg: message,
                            time: this.log.add_time
                        }]
                    }
                }

                // 如果是数组
                if (Array.isArray(message)) {
                    return message.map(item => {
                        if (typeof item === 'object' && item !== null) {
                            return {
                                level: item.level || 'info',
                                msg: item.msg || item.message || String(item),
                                time: item.time || this.log.add_time
                            }
                        } else {
                            return {
                                level: 'info',
                                msg: String(item),
                                time: this.log.add_time
                            }
                        }
                    })
                }

                // 如果是对象
                if (typeof message === 'object' && message !== null) {
                    return [{
                        level: message.level || 'info',
                        msg: message.msg || message.message || JSON.stringify(message),
                        time: message.time || this.log.add_time
                    }]
                }

                // 其他情况
                return [{
                    level: 'info',
                    msg: String(message),
                    time: this.log.add_time
                }]
            } catch (e) {
                console.warn('解析日志消息失败:', e)
                return [{
                    level: 'error',
                    msg: '解析日志消息失败',
                    time: this.log.add_time
                }]
            }
        }
    },
    methods: {
        handleClose() {
            this.$emit('close')
        },

        // 格式化时间
        formatTime(timeStr) {
            if (!timeStr) return '-'
            try {
                const date = new Date(timeStr)
                return date.toLocaleString('zh-CN', {
                    year: 'numeric',
                    month: '2-digit',
                    day: '2-digit',
                    hour: '2-digit',
                    minute: '2-digit',
                    second: '2-digit'
                })
            } catch (e) {
                return timeStr
            }
        },

        // 格式化内存使用
        formatMemory(bytes) {
            if (!bytes || bytes === 0) return '0 B'
            const k = 1024
            const sizes = ['B', 'KB', 'MB', 'GB']
            const i = Math.floor(Math.log(bytes) / Math.log(k))
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
        },

        // 获取标签类型
        getTagType(level) {
            switch (level) {
                case 'info':
                    return 'info'
                case 'error':
                    return 'danger'
                case 'warn':
                    return 'warning'
                case 'debug':
                    return 'primary'
                default:
                    return 'info'
            }
        },

        // 判断是否为堆栈跟踪
        isStackTrace(msg) {
            return typeof msg === 'string' && (
                msg.includes('#0 ') ||
                msg.includes('#1 ') ||
                msg.includes('.php(') ||
                msg.includes('Stack trace:')
            )
        },

        // 获取错误摘要（第一行的错误信息）
        getErrorSummary(msg) {
            if (typeof msg === 'string') {
                const lines = msg.split('\n')
                // 找到第一行不是空行的内容作为错误摘要
                for (const line of lines) {
                    const trimmed = line.trim()
                    if (trimmed && !trimmed.startsWith('#')) {
                        return trimmed
                    }
                }
                return lines[0] || msg
            }
            return String(msg)
        },

        // 获取堆栈跟踪（除了第一行错误信息外的所有内容）
        getStackTrace(msg) {
            if (typeof msg === 'string') {
                const lines = msg.split('\n')
                // 找到第一个堆栈行的位置
                let stackStartIndex = -1
                for (let i = 0; i < lines.length; i++) {
                    if (lines[i].trim().startsWith('#0 ')) {
                        stackStartIndex = i
                        break
                    }
                }

                if (stackStartIndex >= 0) {
                    return lines.slice(stackStartIndex).join('\n')
                }

                // 如果没有找到 #0，但包含.php(，则从第二行开始
                if (msg.includes('.php(')) {
                    return lines.slice(1).join('\n')
                }

                return ''
            }
            return ''
        }
    }
}
</script>

<style scoped>
.log-detail {
    padding: 0;
    height: 100%;
    overflow-y: auto;
}

.log-message-detail {
    margin-top: 20px;
}

.log-message-detail h4 {
    margin: 0 0 12px 0;
    font-size: 16px;
    font-weight: 600;
    color: var(--el-text-color-primary);
    padding-bottom: 8px;
    border-bottom: 1px solid var(--el-border-color-lighter);
}

.message-content {
    border-radius: 4px;
    font-size: 13px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: none;
    overflow-y: visible;
    font-family: 'Consolas', 'Monaco', monospace;
}

.message-item {
    margin-bottom: 15px;
    padding: 8px;
    border-radius: 6px;
    border-left: 4px solid var(--el-border-color);
    background: var(--el-bg-color-page);
}

.message-item.message-level-error {
    border-left-color: var(--el-color-danger);
    /* background: var(--el-color-danger-light-9); */
}

.message-item.message-level-warn {
    border-left-color: var(--el-color-warning);
    background: var(--el-color-warning-light-9);
}

.message-item.message-level-info {
    border-left-color: var(--el-color-info);
    background: var(--el-color-info-light-9);
}

.message-item.message-level-debug {
    border-left-color: var(--el-color-primary);
    background: var(--el-color-primary-light-9);
}

.message-header {
    display: flex;
    align-items: center;
    /* justify-content: space-between; */
    /* margin-bottom: 8px; */
}

.level-tag {
    margin-right: 8px;
}

.message-time {
    font-size: 12px;
    color: var(--el-text-color-secondary);
}

.message-body {
    font-size: 14px;
    line-height: 1.5;
}

.stack-trace {
    /* margin-top: 8px; */
}

.error-summary {
    font-weight: 500;
    margin-bottom: 8px;
    color: var(--el-text-color-primary);
    padding: 8px;
    background: var(--el-fill-color-extra-light);
    border-radius: 4px;
    border-left: 3px solid var(--el-color-danger);
}

.stack-content {
    margin: 0;
    padding: 12px;
    background: var(--el-fill-color-lighter);
    border: 1px solid var(--el-border-color);
    border-radius: 4px;
    font-size: 12px;
    line-height: 1.4;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 400px;
    overflow-y: auto;
    font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
    color: var(--el-text-color-regular);
}

.simple-message {
    font-size: 14px;
    line-height: 1.6;
    color: var(--el-text-color-primary);
    padding: 0 8px;
    /* background: var(--el-fill-color-extra-light); */
    border-radius: 4px;
}

/* Drawer 特定样式 */
:deep(.el-drawer__header) {
    margin-bottom: 0;
    padding: 20px 20px 16px 20px;
    border-bottom: 1px solid var(--el-border-color-lighter);
}

:deep(.el-drawer__body) {
    padding: 20px;
    overflow-y: auto;
}

:deep(.el-descriptions) {
    margin-bottom: 20px;
}

:deep(.el-descriptions__label) {
    width: 80px;
    font-weight: 500;
}

:deep(.el-collapse-item__header) {
    font-size: 13px;
    padding-left: 0;
        height: 35px;
    padding-left: 10px;
}

:deep(.el-collapse-item__content) {
    padding-bottom: 0;
}

/* 响应式调整 */
@media (max-width: 768px) {
    .log-detail-drawer :deep(.el-drawer) {
        width: 100% !important;
    }
}
</style>